﻿using System;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq.SqlClient;
using System.Web;
using IntraVision.Web;
using IntraVision.Web.Security;
using IntraVision.Web.Filter;
using Model;
using System.Text;

using GeneratedCode;

public struct NotarialFormAction
{
    private string name, action, href;

    public string Name { get { return name; } }
    public string Action { get { return action; } }
    public string Href { get { return href; } }

    public NotarialFormAction(string name, string href, string action)
    {
        this.name = name;
        this.action = action;
        this.href = href;
    }
}

[Security]
public class NotarialFormController : TableController<NotarialServiceDataContext, NotarialForm>
{
    #region filter fields

    protected int _StatusId
    {
        get { return Session["tb_nf_statusid"] != null ? Convert.ToInt32(Session["tb_nf_statusid"]) : 0; }
        set { Session["tb_nf_statusid"] = value.ToString(); }
    }

    protected int _ActMode
    {
        get { return Session["tb_actmode"] != null ? Convert.ToInt32(Session["tb_actmode"]) : 0; }
        set { Session["tb_actmode"] = value.ToString(); }
    }

    protected bool _ShowInvalid
    {
        get { return _StatusId == -1; }
    }

    protected int _RangeId
    {
        get { return Session["tb_rangeid"] != null ? Convert.ToInt32(Session["tb_rangeid"]) : 0; }
        set { Session["tb_rangeid"] = value.ToString(); }
    }

    protected int[] _Ids { get; set; }

    #endregion

    public override void Create()
    {
        throw new IntraVisionWebException(404);        
    }

    public override void Delete()
    {
        if (!CanDelete())
            throw new InvalidOperationException();

        using (var dc = new NotarialServiceDataContext())
        {
            try
            {
                if (String.IsNullOrEmpty(Request["id"]))
                    throw new ArgumentException("Идентификатор записи не передан");

                int[] ids = null;
                if (Request["id"].IndexOf(',') > 0)
                    ids = RequestHelper.GetIdsFromString(Request["id"]);
                else
                {
                    ids = new int[1];
                    if (!Int32.TryParse(Request["id"], out ids[0]))
                        throw new ArgumentException("Неправильный идентификатор");
                }

                var deleted = new List<NotarialForm>();

                var table = dc.GetTable<NotarialForm>();
                foreach (var i in ids)
                {
                    var entity = table.Where(t => t.Id == i).FirstOrDefault();
                    if (entity != null)
                    {
                        entity.StatusId = 1;
                        entity.OrderId = null;
                        entity.UserId = (Session["User"] as User).Id;
                        entity.Comment = string.Empty;
                        entity.IsInAct = false;
                        entity.IsInEnot = false;
                    }
                }

                if (dc.GetChangeSet().Updates.Count > 0)
                    dc.SubmitChanges();
            }
            catch (Exception ex)
            {
                if (!string.IsNullOrEmpty(Request["json"]))
                {
                    RenderJSON(new AJAXResult(ex));
                    return;
                }
                ViewData.Exceptions.Add(ex);
            }

            if (!string.IsNullOrEmpty(Request["json"]))
            {
                var result = new AJAXResult {Id = Request["id"]};
                RenderJSON(result);
            }
            else
                List();
        }
    }

    protected override void EntityLoaded(NotarialServiceDataContext dc, NotarialForm entity)
    {
        if (!string.IsNullOrEmpty(Request["popup"]))
        {
            LayoutPath = "~/views/layouts/popup.haml";
            TemplatePath = "~/views/notarialform/form.haml";

            ViewData["popup"] = true;
            ViewData["readonly"] = true;
        }

        ViewData["statuses"] = dc.NotarialFormStatus.ToList();

        RegisterScript("notarialform/form.js");
        base.EntityLoaded(dc, entity);
    }

    protected override IQueryable ConvertQueryToResult(NotarialServiceDataContext dc, IQueryable<NotarialForm> query)
    {
        return (from q in query    
                select new
                {
                       Id = q.Id,
                       Name = q.FullName,
                       CreateDate = q.CreateDate,
                       ModifyDate = q.ModifyDate,
                       EndDate = q.EndDate,
                       OrderId = q.OrderId,
                       NotarialFormStatusName = q.NotarialFormStatus.Name,
                       SerialNumberName = q.NotarialFormSerialNumber.Name,
                       IsInAct = q.IsInAct,
                       IsInEnot = q.IsInEnot,
                });        
    }

    public override void List()
    {
        CheckStatusId();
        CheckRangeId();

        if (CanDelete())
            ViewData["candelete"] = true;

        ViewData["actmode"] = _ActMode;

        //если это НЕ ajax-request
        if (String.IsNullOrEmpty(Request["nolayout"]))
        {
            RegisterScript("notarialform/list.js");
            RegisterStylesheet("order/order.css");
        }
        RegisterScript("jquery.blockUI.js");

        base.List();     
    }

    protected override IQueryable<NotarialForm> Search(IQueryable<NotarialForm> query)
    {
        int oid;
        var searchStr = State["tb_search"] != null ? State["tb_search"].Trim() : "";
        if (!string.IsNullOrEmpty(searchStr))
        {
            var search = String.Format("%{0}%", searchStr.Trim().ToLower());
            //поиск по номеру бланка
            if ((Int32.TryParse(searchStr, out oid)) && oid > 0)
                return query.Where(q => SqlMethods.Like(q.Name.ToString(), search));
            return null;
        }
        return query;
    }

    protected override void CreateFilterConditions(NotarialServiceDataContext dc)
    {
        base.CreateFilterConditions(dc);

        Filter = new Filter<NotarialForm>();
        var fc = Filter.Conditions;
        fc.Add(new NumericFilterCondition<NotarialForm>("name", "Номер бланка"));
        fc.Add(new DateFilterCondition<NotarialForm>("createdate", "Дата получения"));
        fc.Add(new DateFilterCondition<NotarialForm>("modifydate", "Дата изменения"));
        fc.Add(new DateFilterCondition<NotarialForm>("enddate", "Дата выдачи"));
        //fc.Add(new SelectFilterCondition<NotarialForm>("statusid", "Статус", (from s in dc.NotarialFormStatus orderby s.Id select s)));
        fc.Add(new NumericFilterCondition<NotarialForm>("orderid", "Номер заявки"));
        fc.Add(new BoolFilterCondition<NotarialForm>("IsInAct", "Учтен в акте"));
        fc.Add(new BoolFilterCondition<NotarialForm>("IsInEnot", "Экспортирован в еНот"));
        fc.Add(new ManualFilterCondition<NotarialForm>("manual", "Дополнительно"));
    }

    protected override void CustomInit(NotarialServiceDataContext dc)
    {
        LoadStatusesInfo(dc);

        base.CustomInit(dc);
    }

    public void GetStatusesInfo()
    {
        using (var dc = new NotarialServiceDataContext())
        {
            LoadStatusesInfo(dc);
        }
        LayoutPath = "none";
        TemplatePath = "~/views/notarialform/_statuslist.haml";
        RenderView();
    }

    protected override IQueryable<NotarialForm> CustomFilter(NotarialServiceDataContext dc, IQueryable<NotarialForm> query)
    {
        if (_RangeId > -1)
            query = query.Where(q => q.RangeId == _RangeId || _RangeId == 0);

        if (_ShowInvalid)
            query = query.Where(q => q.NotarialFormStatus.IsInvalid);
        else if (_StatusId > -1)
            query = query.Where(q => q.StatusId == _StatusId || _StatusId == 0);

        if (CanDelete())
            query = query.Where(q => q.IsInAct == (_ActMode == 1));

        if (ViewData.ContainsKey("excel"))
            query = query.Where(q => _Ids != null && _Ids.Contains(q.Id)); 

        return query;
    }

    private void CheckStatusId()
    {
        if (!String.IsNullOrEmpty(Request["tb_nf_statusid"]))
        {
            int statusId;
            if (Int32.TryParse(Request["tb_nf_statusid"], out statusId))
                _StatusId = statusId;
        }
    }

    private void CheckRangeId()
    {
        if (!String.IsNullOrEmpty(Request["tb_rangeid"]))
        {
            int rangeId;
            Int32.TryParse(Request["tb_rangeid"], out rangeId);

            if (rangeId > -1)
                _RangeId = rangeId;
        }
    }

    private void LoadStatusesInfo(NotarialServiceDataContext dc)
    {
        var statuses = (from s in dc.NotarialFormStatus 
                        orderby s.Id 
                        where !s.IsInvalid
                        select new StatusInfo
                                (
                                    s.Id, 
                                    s.Name, 
                                    dc.NotarialForm.Count(n => n.StatusId == s.Id 
                                                            && (_RangeId == 0 || n.RangeId == _RangeId))
                                )
                       ).ToList();

        var subStatuses = (from s in dc.NotarialFormStatus 
                           orderby s.Id 
                           where s.IsInvalid
                           select new StatusInfo
                                (
                                    s.Id, 
                                    s.Name, 
                                    dc.NotarialForm.Count(n => n.StatusId == s.Id 
                                                            && (_RangeId == 0 || n.RangeId == _RangeId))
                                )
                          ).ToList();

        var invalidRoot = new StatusInfo(-1, "Недействителен", subStatuses.Sum(s => s.OrdersCount));
        invalidRoot.SubStatuses = subStatuses;

        statuses.Add(invalidRoot);
        statuses.Add(new StatusInfo(0, "Всего", dc.NotarialForm.Count(n => _RangeId == 0 || n.RangeId == _RangeId)));

        ViewData["statuses"] = statuses;
        ViewData["statusid"] = _StatusId;
        ViewData["range"] = dc.NotarialFormRange.FirstOrDefault(r => r.Id == _RangeId);
    }

    private bool CanDelete()
    {
        return  (_ShowInvalid || _StatusId > 2);
    }

    public void ChangeActMode()
    {
        int mode = 0;
        if (int.TryParse(Request["mode"], out mode) && mode > -1)        
            _ActMode = mode;        
    }

    public void MakeAct()
    {
        
    }

    public override void Excel()
    {
        if (string.IsNullOrEmpty(Request["ids"]))
            throw new ArgumentException("Идентификатор записи не передан");

        int[] ids = null;
        if (Request["ids"].IndexOf(',') > 0)
            ids = RequestHelper.GetIdsFromString(Request["ids"]);
        else
        {
            ids = new int[1];
            if (!int.TryParse(Request["ids"], out ids[0]))
                throw new ArgumentException("Неправильный идентификатор");
        }
        _Ids = ids;

        using (var dc = new NotarialServiceDataContext())
        {
            var forms = dc.NotarialForm.Where(f => ids.Contains(f.Id)).Select(f => new BadNotarialFormsGeneratedClass.NotarialFormBadReportItem(f)).ToList();       
            Response.ContentType = "application/octet-stream";
            Response.AppendHeader("Content-Disposition", "attachment;filename=\"" + string.Format("Акт списания бланков_{0}.docx", DateTime.Now) + "\"");
            Response.HeaderEncoding = Encoding.GetEncoding("windows-1251");
            Response.ContentEncoding = Encoding.GetEncoding("windows-1251");
            var report = new BadNotarialFormReport();
            var bytes = report.GetReport(forms);
            Response.BinaryWrite(bytes);
            Response.Flush();
            Response.End();
        }
    }

    public void SetInActAttribute()
    {
        using (var dc = new NotarialServiceDataContext())
        {
            if (string.IsNullOrEmpty(Request["ids"]))
                throw new ArgumentException("Идентификатор записи не передан");

            int[] ids = null;
            if (Request["ids"].IndexOf(',') > 0)
                ids = RequestHelper.GetIdsFromString(Request["ids"]);
            else
            {
                ids = new int[1];
                if (!int.TryParse(Request["ids"], out ids[0]))
                    throw new ArgumentException("Неправильный идентификатор");
            }

            var list = dc.NotarialForm.Where(nf => ids.Contains(nf.Id));

            foreach (var nf in list)
                nf.IsInAct = true;

            if (dc.GetChangeSet().Updates.Count > 0)
                dc.SubmitChanges();            
        }
    }

    public void GetActionMenu()
    {
        int notarialFormId;
        var user = Session["user"] as User;

        if (user != null && Int32.TryParse(Request["notarialformid"], out notarialFormId) && notarialFormId > 0)
        {
            var actions = new List<NotarialFormAction>();

            using (var dc = new NotarialServiceDataContext())
            {
                var entity = dc.NotarialForm.FirstOrDefault(o => o.Id == notarialFormId);
                if (entity.Id > 0 && entity != null)
                {
                    var statuses = (from s in dc.NotarialFormStatus
                                    where s.Id != entity.StatusId
                                    select s).OrderBy(s => s.Id).ToList();

                    foreach (var s in statuses)
                    {
                        var actionStr = string.Format("return changeStatus({0},{1});", entity.Id, s.Id);
                        actions.Add(new NotarialFormAction(s.Name, "#", actionStr));
                    }

                    ViewData["entity"] = entity;
                }
            }
            LayoutPath = "none";
            TemplatePath = "~/views/notarialform/actionmenu.haml";
            ViewData["actions"] = actions;

            RenderView();
        }
    }

    public void ChangeStatus()
    {
        int id = 0, statusId = 0;

        if (Int32.TryParse(Request["id"], out id) && id > 0
            && Int32.TryParse(Request["statusid"], out statusId) && statusId > 0)
        {
            try
            {
                using (var dc = new NotarialServiceDataContext())
                {
                    var entity = dc.NotarialForm.First(nf => nf.Id == id);
                    entity.StatusId = statusId;
                    dc.SubmitChanges();
                }
            }
            catch (InvalidOperationException ex)
            {
                RenderJSON(new AJAXResult(ex));
                return;
            }
            catch (NullReferenceException ex)
            {
                RenderJSON(new AJAXResult(ex));
                return;
            }
            catch (Exception ex)
            {
                RenderJSON(new AJAXResult(ex));
                return;
            }
            RenderJSON(new AJAXResult(true));
        }
        else
        {
            RenderJSON(new ArgumentException("Аргументы заданы некорректно."));
            return;
        }
    }

    public void GroupStatusEditor()
    {
        using (var dc = new NotarialServiceDataContext())
        {
            ViewData["statuses"] = dc.NotarialFormStatus.ToList();
            ViewData["ids"] = new List<int>();
        }

        LayoutPath = "~/views/layouts/page.haml";
        TemplatePath = "~/views/" + Name + "/groupstatuseditor.haml";

        RegisterFormScripts();
        RegisterScript("notarialform/groupstatuseditor.js");

        RegisterScript("jquery.multipleselect.js", "jquery.autocomplete.js", "jquery.elastic.js", "jquery.blockUI.js", "jquery.notifica.min.js");
        RegisterStylesheet("autocomplete/autocomplete.css");

        RenderView();
    }

    public void ChangeStatusForGroup()
    {
        using (var dc = new NotarialServiceDataContext())
        {
            try
            {
                if (string.IsNullOrEmpty(Request["ids"]))
                    throw new ArgumentException("Идентификаторы бланков не переданы");

                int[] ids;
                if (Request["ids"].IndexOf(',') > 0)
                    ids = RequestHelper.GetIdsFromString(Request["ids"]);
                else
                {
                    ids = new int[1];
                    if (!int.TryParse(Request["ids"], out ids[0]))
                        throw new ArgumentException("Неправильный идентификатор балнка.");
                }

                var statusId = 0;
                if (string.IsNullOrEmpty(Request["statusid"]) || !int.TryParse(Request["statusid"], out statusId) ||
                    statusId < 1)
                    throw new ArgumentException("Неправильный идентификатор статуса.");


                foreach (var entity in ids.Select(id => dc.NotarialForm.FirstOrDefault(f => id == f.Id)))
                {
                    entity.StatusId = statusId;
                    entity.UserId = (Session["User"] as User).Id;
                }

                if (dc.GetChangeSet().Updates.Count > 0)
                        dc.SubmitChanges();
            }
            catch (Exception ex)
            {
                RenderJSON(new AJAXResult(ex));
                return;
            }

            var result = new AJAXResult {Id = Request["id"], IsOK = true, Description = "Операция выполнена успешно."};
            RenderJSON(result);            
        }
    }
}